/*
 配置 vscode 调试

 https://code.visualstudio.com/docs/cpp/config-linux
 https://blog.csdn.net/gbmaotai/article/details/88974988
 https://code.visualstudio.com/docs/editor/variables-reference

 centos7 gcc 支持32位
 yum install -y libgcc.i686
 yum install -y glibc-devel-2.17-317.el7.i686

 注意：
  这个测试程序只能用于32位，64位会出现问题
  在x86（32位机器）平台下，GCC编译器默认4字节对齐

  __attribute__((packed)) 让所作用的结构体取消在编译过程中的优化对齐，按照实际占用字节数进行对齐。
  __attribute__((aligned (n))) 让所作用的结构体成员对其在n字节边界上，如果结构体中有成员变量的字节长度大于n, 则按照最大成员变量的字节长度来对齐。
*/

#include <stdlib.h>
#include <stdio.h>

#define JZ_ALIGN(x, a) (((x)+(a)-1)&~((a)-1))

struct dog{
    int age;      // 4
    char *name;   // 4
    int height;   // 4
    char type;    // 1
}__attribute__((packed));


struct cat{
    int age;
    char *name;
    int height;
    char type;
}__attribute__((aligned(4)));

void print_test(const char *format, ...)
{
    printf("&format=%p, format=%p \r\n", &format, format); // 也可以写 %#X 或 %#x
    printf("arg1 %c %c %c \r\n", *format, *(format+1), *(format+2)); // 会溢出

    char *p1 = (char*)&format;
    char **p2 = (char **)p1;
    printf("p1=%p, *p2=%p  \r\n", p1, *p2);
    printf("arg1 %c %c %c \r\n", **p2, *(*p2+1), *(*p2+2)); // 会溢出

    p1 += sizeof(char *);
    printf("arg2 %d \r\n", *((int*)p1)); // 会溢出

    p1 += sizeof(int);
    p2 = (char **)p1;
    printf("arg3 %c %c %c \r\n", **p2, *(*p2+1), *(*p2+2)); // 会溢出

    p1 += sizeof(char *);
    printf("arg4 %d \r\n", *((int*)p1)); // 会溢出

    p1 += sizeof(int);
    struct dog pd = *((struct dog*)p1);
    printf("arg5 age:%d,  height:%d,  name:%s \r\n", pd.age,  pd.height, pd.name);

    // p1 += sizeof(struct dog);
    // p1 += 16; // 虽然压缩对齐，但是还是要跳过4字节
    p1 += JZ_ALIGN(sizeof(struct dog), 4);
    printf("arg6 %c \r\n", *((char*)p1)); 

    p1 += ((sizeof(char) + 3) & ~3); // 虽然压缩对齐，但是还是要跳过4字节
    int x = ((sizeof(char) + 3) & ~3);
    printf("arg7 %f \r\n", *((double*)p1)); // 参数传递的是 double 类型
}


int main(int argc, char *argv)
{
    struct dog d = {10, "tom", 20, 'd'};

    printf("sizeof(char*)=%d\r\n", sizeof(char*));
    printf("sizeof(int)=%d\r\n", sizeof(int));
    
    printf("sizeof(dog)=%d\r\n", sizeof(struct dog));
    printf("sizeof(cat)=%d\r\n", sizeof(struct cat));

    print_test("abc", 123, "bcd", 678, d,'m', 2.79);

    return EXIT_SUCCESS;
}